package cn.westv.scps.dao.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;

import com.alibaba.fastjson.JSON;

import cn.westv.scps.dao.BaseDao;
import cn.westv.scps.utils.Page;

/**
 * @Description:
 * @Author: jiawenbin
 * @CreateDate: 20170606
 */
public class BaseDaoImpl implements BaseDao {
	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	// 带条件查询
	public <T> List<T> find(String hql, Class<T> entityClass, Object[] params) {
		Query query = this.getSession().createQuery(hql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}
		return (List<T>) query.list();
	}

	// 获取一条，根据主键id
	public <T> T get(Class<T> entityClass, Serializable id) {
		return (T) this.getSession().get(entityClass, id);
	}

	// 分页查询，查询两次，一次查询总数，一次查询分页记录
	public <T> Page<T> findPage(String hql, Page<T> page, Class<T> entityClass, Object[] params) {

		Query query = this.getSession().createQuery(hql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}

		// 查询一次，获取记录总数
		// int count = query.list().size(); // 可以优化？？？？ "select count(*) " +hql
		Query countQuery = this.getSession().createQuery("select count(*) " + hql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				countQuery.setParameter(i, params[i]);
			}
		}
		int count = ((Number) (countQuery.uniqueResult())).intValue();
		page.setTotalRecord(count);

		// 设置分页
		query.setFirstResult((page.getPageNo() - 1) * page.getPageSize()); // 设置开始位置
		query.setMaxResults(page.getPageSize()); // 设置获取几条
		page.setResults((List<T>) query.list());

		return page;
	}

	@Override
	public <T> Page<T> findPageBySql(String sql, Page<T> page, Class<T> entityClass, Object[] params) {
		Query query = this.getSession().createSQLQuery(sql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}

		// 查询一次，获取记录总数
		int count = query.list().size(); // 可以优化？？？？ "select count(*) " +hql
		page.setTotalRecord(count);

		// 设置分页
		query.setFirstResult((page.getPageNo() - 1) * page.getPageSize()); // 设置开始位置
		query.setMaxResults(page.getPageSize()); // 设置获取几条

		page.setResults((List<T>) query.list());

		return page;
	}

	// 新增和修改，hibernate根据id是否为null自动判断
	public <T> void saveOrUpdate(T entity) {
		this.getSession().saveOrUpdate(entity);
	}

	// 集合保存，这时新增还是修改，就自动判断，调用时是否简洁。适合批量新增和修改时。（Mrecord控件）
	public <T> void saveOrUpdateAll(Collection<T> entitys) {
		for (T entity : entitys) {
			this.saveOrUpdate(entity);// 为什么hibernate批量操作时，要用循环一条一条记录去更新？
		}
	}

	// 按主键id删除
	public <T> void deleteById(Class<T> entityClass, Serializable id) {
		this.getSession().delete(get(entityClass, id));
	}

	// 批量删除
	public <T> void delete(Class<T> entityClass, Serializable[] ids) {
		for (Serializable s : ids) {
			deleteById(entityClass, s);
		}
	}

	@Override
	public <T> List<T> querySQL(String sql, Object[] params, Class<T> entityClass) {
		SQLQuery query = getSession().createSQLQuery(sql);
		for (int i = 0; i < params.length; i++) {
			query.setEntity(i, params[i]);
		}
		return (List<T>) query.setResultTransformer(Transformers.aliasToBean(entityClass));
	}

	@Override
	public <T> void save(T entity) {
		this.getSession().save(entity);

	}

	@Override
	public <T> void update(T entity) {
		this.getSession().update(entity);
	}

	@Override
	public <T> T  queryHQL(String HQL, Object[] params, Class<T> entityClass) {
		Query query = this.getSession().createQuery(HQL);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				query.setParameter(i, params[i]);
			}
		}
		Object uniqueResult = query.uniqueResult();
//		String jsonString = JSON.toJSONString(uniqueResult);
//		System.err.println(jsonString);
		return (T) uniqueResult;
	}

}
